<template>
    <el-popover placement="right-start" :width="180">
        <template #reference>
            <el-form ref="formRef" :model="state">
                <el-form-item prop="password" :rules="[{ validator }]">
                    <el-input
                        v-model="state.password"
                        type="password"
                        show-password
                        placeholder="请输入密码"
                        prefix-icon="el-icon-lock"
                        clearable
                        @input="(value) => emits('update:modelValue', value)"
                    />
                </el-form-item>
            </el-form>
        </template>
        <ul class="rules">
            <li v-for="(rule, index) in state.rules" :key="index" :class="rule.status">
                <span>
                    <el-icon><el-icon-success-filled /></el-icon>
                    {{ rule.text }}
                </span>
                <ul v-if="rule.children" class="sub-rules">
                    <li v-for="(sub, i) in rule.children" :key="i" :class="sub.status">
                        {{ sub.text }}
                    </li>
                </ul>
            </li>
        </ul>
    </el-popover>
</template>

<script setup>
import { reactive, ref, watch } from "vue";
import { PasswordValidRules } from "./const";

const emits = defineEmits(["update:modelValue", "validate"]);
const props = defineProps(["modelValue"]);
const formRef = ref(null);
const state = reactive({ rules: PasswordValidRules(), visible: false, valid: false, password: props.modelValue });

const validator = (_, value) => {
    let validCount = 0;

    state.rules.forEach((item) => {
        if (item.children && item.min !== void 0) {
            let subRuleValidCount = 0;
            item.children.forEach((sub) => {
                const matched = value.match(sub.regexp);
                if (matched && matched.length) {
                    subRuleValidCount++;
                    sub.status = "success";
                } else {
                    sub.status = "error";
                }
            });
            if (subRuleValidCount >= item.min) {
                validCount++;
                item.status = "success";
            } else {
                item.status = "error";
            }
        } else {
            const matched = value.match(item.regexp);
            if (matched && matched.length) {
                validCount++;
                item.status = "success";
            } else {
                item.status = "error";
            }
        }
    });
    if (!value) {
        emits("validate", false);
        return new Error("请设置密码");
    }
    if (validCount !== state.rules.length) {
        emits("validate", false);
        return new Error("密码不符合规范，请重新输入");
    }

    emits("validate", true);
    return true;
};

const validate = () => {
    return formRef.value.validate();
};

defineExpose({ validate });
watch(
    () => props.modelValue,
    (value) => (state.password = value),
);
</script>

<style lang="scss" scoped>
.rules {
    line-height: 24px;
    font-size: 12px;
    > li {
        padding-bottom: 5px;
        &.success {
            span {
                :deep(.el-icon) {
                    color: var(--el-color-success);
                }
            }
        }
        span {
            display: flex;
            align-items: center;
            :deep(.el-icon) {
                width: 12px;
                height: 12px;
                margin-right: 6px;
            }
        }
    }
    .sub-rules {
        padding-left: 18px;
        li {
            &.success {
                color: var(--el-color-success);
            }
        }
    }
}
</style>
